package com.extra_archive.project.iisu.view.detail.presentation 
{
	import flash.utils.getTimer;
	import flash.filters.BlurFilter;
	import iisu.Vector3;
	import iisu.iisuEvent.ClickEvent;
	import iisu.util.GestureModel;

	import com.extra_archive.framework.core.mvc.model.IModel;
	import com.extra_archive.framework.core.mvc.view.IComponentView;
	import com.extra_archive.framework.utils.NumberUtils;
	import com.extra_archive.project.iisu.model.ARModelEvent;
	import com.extra_archive.project.iisu.view.BasicSpace3DView;
	import com.extra_archive.project.iisu.view.detail.ARDetailView;
	import com.greensock.TweenMax;
	import com.greensock.easing.Back;
	import com.greensock.easing.Cubic;

	import org.papervision3d.materials.MovieMaterial;
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.objects.primitives.Plane;

	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.geom.Vector3D;
	import flash.utils.getDefinitionByName;
	import flash.utils.setTimeout;

	/**
	 * @ Class Name : PresentationView.as
	 * @ Author : seenix
	 * @ Up Date : 2010. 5. 7.
	 */
	public class PresentationView extends BasicSpace3DView implements IComponentView 
	{
//		[Embed(source="/../bin/img/detail/presentation/paper_red.png")]
//		private var _frame : Class;
		
		private var _contentsContainer : DisplayObject3D;
		private var _menuContainer : DisplayObject3D;
		private var _menus : Vector.<MenuPlane> = new Vector.<MenuPlane>();
		private var _prevIndex : int = 0;
		private var _index : int = 0; //0-4
		private var _contents : Vector.<ContentPlane> = new Vector.<ContentPlane>();
		
		private var _prevRightHandX : Number;
		private var _prevHeadY : Number;
		
		private var _isActive : Boolean;
		private var _isContentGrabbed : Boolean;
		
		private var _frame : Plane;
		
		private var _menuPositions: Vector.<Vector3D> = new Vector.<Vector3D>();
		
		private var _menuAngle : Number = 0;
		
		private var _jumpStarted : Boolean;
		
		public function PresentationView(model : IModel = null, detailView : ARDetailView = null)
		{
			super(model);
			
			//if (GestureModel(_model).isGestureControl) GestureModel(_model).addEventListener(ClickEvent.CLICK, onTriggerUp);
			
			initialize();
		}

		//--------------------------------------------------------------------------
		//
		//    Event Listeners
		//
		//--------------------------------------------------------------------------

		//--------------------------------------------------------------------------
		//
		//    Public Methods
		//
		//--------------------------------------------------------------------------
		
		override public function initialize() : void 
		{
			createContentsContainer();
			createMenuContainer();
			createContents();
			createContentFrame();
			createMenus();
			
			addEventListener(Event.ENTER_FRAME, update, false, 0, true);
		}

		override public function update(event : Event = null) : void 
		{
			super.update();
			//TODO : 제스쳐 데이터에 따른 반응
			if (!GestureModel(_model).isGestureControl) return;

			//setMenu();
			if (_isActive) 
			{
				setContentPosition();
				setMenuPosition();
				//hitTestMenu();
				grabMenu();
				//두손내밀면 자기자리로
				grabContent();
				
				setContentRotation();
				
				//if (getHeadVelocityY() > 0.1) resetKilledMenu();
				if (GestureModel(_model).head.z > 1.35)
				{
					
					resetKilledMenu();
				}
			}
			
			if (!_isActive && _isContentGrabbed) killContent();
		}

		public function live() : void
		{
			addEventListener(Event.ENTER_FRAME, update, false, 0, true);
			_contentsContainer.addChild(_contents[0]);
			intro();
		}
		
		public function kill() : void
		{
			_index = 0;
			_isActive = false;
			_isContentGrabbed = false;
			
			// menu reset
			for each (var menu : MenuPlane in _menus)
			{
				menu.scale = 0.1;
				menu.y = 80;
				menu.z = -10;
				menu.alpha = 0;
			}
			
			// conents reset
			for each (var content :ContentPlane in _contents)
			{
				content.alpha = 1;
				content.scale = 1;
				content.x = content.y = content.rotationZ = 0;
				_contentsContainer.removeChild(content);
			}
			
			removeEventListener(Event.ENTER_FRAME, update);
		}
		
		//--------------------------------------------------------------------------
		//
		//    Event Listeners
		//
		//--------------------------------------------------------------------------
		
		// test function
		private function onTriggerUp(event : ClickEvent) : void 
		{
			if (_index >= 4) 
			{
				_contentsContainer.removeChild(_contents[_prevIndex]);
				outro();
				return;
			}
			
			// 메뉴선택
			TweenMax.to(_menus[_index], 0.8, {x : _contentsContainer.x, y : _contentsContainer.y, ease: Cubic.easeInOut});
			TweenMax.to(_menus[_index], 0.3, {delay : 0.6, alpha: 0});
			setTimeout(changeContent, 800, [_index]);
			
			_prevIndex = _index;
			_index++;
		}

		//--------------------------------------------------------------------------
		//
		//    Private Methods
		//
		//--------------------------------------------------------------------------
		
		private function intro() : void
		{
			TweenMax.to(_contentsContainer, 0.2, {scale : 0.44, rotationX : 0, ease : Cubic.easeInOut});
			TweenMax.to(_contentsContainer, 0.5, {delay : 0.15, scale : 0.8, ease : Cubic.easeOut});
			//setTimeout(setContentPosition, 190);
			
			var mx : int;
			var my : int; // -200
			var mz : int;
			var ry : int;
			var rx : int;
			var i : uint;
			for each (var menu: Plane in _menus)
			{
				i = uint(menu.name.slice(-1));
				//mx = -370 + i * 250;
				mx = 200 * Math.cos(i * (Math.PI * 2 / 4));
				mz = 200 * Math.sin(i * (Math.PI * 2 / 4));
				my = NumberUtils.randomIntInRange(230, 280);
				rx = NumberUtils.randomIntInRange(5, 10);
				ry = NumberUtils.randomIntInRange(0, 0);
				TweenMax.to(menu, 0.7, {delay : 0.1 * i, alpha:1, scale : 1, rotationX : rx, rotationY : ry, bezier:[{x:0, y: 200, z: -200}, {x:mx, y: my, z: mz}], ease: Cubic.easeOut});
				_menuPositions.push(new Vector3D(mx, my, mz));
			}
			
			setTimeout(function(): void
			{
				_isActive = true;
			}, 650);
		}
		
		private function outro() : void
		{
			_isActive = false;
			
			TweenMax.to(_contentsContainer, 0.6, {scale : 0.44, y : -30, z : -150, ease : Cubic.easeOut});
			TweenMax.to(_contentsContainer, 0.3, {delay : 0.55, rotationX : 90, ease : Cubic.easeInOut});
			//TweenMax.to(_contentsContainer, 0.2, {delay : 0.4, alpha : 0, ease : Cubic.easeOut});
			
			setTimeout(function(): void
			{
				_model.dispatchEvent(new ARModelEvent(ARModelEvent.DETAIL_TO_LIST));
			}, 800);
		}
		
		private function createContentsContainer() : void 
		{
			_contentsContainer = new DisplayObject3D();
			_contentsContainer.scale = 0.44;
			_contentsContainer.rotationX = 90;
			_contentsContainer.y = 80;
			_contentsContainer.z = -150;
			scene.addChild(_contentsContainer);
		}
		
		private function createMenuContainer() : void 
		{
			_menuContainer = new DisplayObject3D();
			scene.addChild(_menuContainer);
		}
		
		private function createContents() : void 
		{
			var plane : ContentPlane;
			var i : uint, len : uint = 5;
			for (i; i < len; ++i)
			{
				plane = new ContentPlane(i);
				plane.useOwnContainer = true;
				_contents.push(plane);
			}
			_contentsContainer.addChild(_contents[0]);
		}
		
		private function createContentFrame() : void 
		{
			var mc : MovieClip = getLibraryAsset("bin_frame") as MovieClip;
			TweenMax.to(mc, 0, {tint : 0xFFFFFF});
			var mat: MovieMaterial = new MovieMaterial(mc, true, true);
			_frame = new Plane(mat, mat.movie.width, mat.movie.height);
			_frame.useOwnContainer = true;
			_frame.alpha = 0;
			_contentsContainer.addChild(_frame);
		}

		private function createMenus() : void 
		{
			var mc : MovieClip;
			var menu : MenuPlane;
			var mat : MovieMaterial; 
			var i : uint, len : uint = 4;
			for (i; i < len; ++i)
			{
				mc = getLibraryAsset("menu" + i) as MovieClip;
				TweenMax.to(mc, 0, {tint : 0xFFFFFF});
				mat = new MovieMaterial(mc, true);
				mat.doubleSided = true;
				mat.smooth = true;
				menu = new MenuPlane(mat, mat.bitmap.width, mat.bitmap.height);
				menu.name = "menu" + i;
				menu.scale = 0.1;
				//menu.x = -370 + i * 250;
				menu.y = 80;
				menu.z = -10;
				//menu.alpha = 0;
				menu.useOwnContainer = true;
				scene.addChild(menu);
				_menus.push(menu);
			}
		}
		
		private function changeContent(id : uint, newId :uint) : void
		{
			if (_contents[newId].root) _contentsContainer.removeChild(_contents[newId]);
			//이전거 사라지게
			TweenMax.to(MovieMaterial(_contents[id].clip.material).movie, 0.25, {colorMatrixFilter:{brightness:3}, ease: Cubic.easeOut});
			TweenMax.to(_contents[id], 0.35, {delay: 0.2, scale: 0.3, ease: Cubic.easeInOut});
			TweenMax.to(_contents[id], 0.25, {delay: 0.4, alpha: 0, onComplete : function():void{_contentsContainer.removeChild(_contents[id])}});
			_contents[id].kill();
			
//			// 프레임 작아졌다 커지게
//			TweenMax.to(_frame, 0.6, {alpha : 1, scale : 0.3, ease : Cubic.easeOut});
//			TweenMax.to(_frame, 0.4, {delay : 0.6, scale : 1, ease : Cubic.easeInOut});
//			TweenMax.to(_frame, 0.3, {delay : 0.7, alpha : 0, ease : Cubic.easeOut});
			
			//새로운 거 등장
			_contents[newId].alpha = 0;
			//_contents[id+1].z = 200;
			_contents[newId].scale = 0.3;
			_contentsContainer.addChild(_contents[newId]);
			TweenMax.to(_contents[newId], 0.7, {delay : 0.5, z : 0, alpha : 1, scale : 1, ease: Back.easeOut});
			TweenMax.to(MovieMaterial(_contents[newId].clip.material).movie, 0.25, {colorMatrixFilter:{brightness:1}, ease: Cubic.easeOut});
			_contents[newId].live();
			
			//_index = newId;
		}
		
		private function grabMenu() : void 
		{
			if (_index >= 4) return;
		
			//var handPositionX : Number = GestureModel(_model).rightHand.x;
			//var handPositionY : Number = GestureModel(_model).rightHand.z;
			var handPositionX : Number = GestureModel(_model).hand1_3D.x;
			var handPositionY : Number = GestureModel(_model).hand1_3D.z;
			var distance : Number = Point.distance(new Point(_contentsContainer.x, _contentsContainer.y), new Point(_menus[_index].x, _menus[_index].y));
		
			if (GestureModel(_model).rightHand.z > 1.3)
			{
				if (_menus[_index].isKilled) return;
				if (!_menus[_index].isGrabbed)
				{
					_menus[_index].isGrabbed = true;
				    _menus[_index].filters = [];
					if (!GestureModel(_model).hand1_3D.x == 0 && !GestureModel(_model).hand1_3D.z == 0) TweenMax.to(_menus[_index], 1, {alpha:1, scale : 1, bezier:[{x:handPositionX - (handPositionX * 0.32) * -1024, y: 0, z: -200}, {x:handPositionX - (handPositionX * 0.35) * -1024, y: handPositionY * 500 - 500}]});
				}
				else 
				{
					
					if (!GestureModel(_model).hand1_3D.x == 0 && !GestureModel(_model).hand1_3D.z == 0) TweenMax.to(_menus[_index], 0.4, {alpha:1,  scale:1, x : handPositionX - (handPositionX * 0.32) * -1024, y : handPositionY * 500 - 500});
					//TweenMax.to(_menus[_index], 0.4, {x : handPositionX * 400, y : handPositionY * 768});
				}
			}
			else
			{
				if (distance < 200 && GestureModel(_model).hand1.x < 0.1) throwMenu(_menus[_index]);
				if (_menus[_index].isGrabbed && !_menus[_index].isKilled)
				{
					if (GestureModel(_model).hand1_3D.x == 0 || GestureModel(_model).hand1_3D.z == 0)
					{
						//만약 손의 위치가 0일때는 마지막 좌표
					}
					else
					{
						//손이 위에 있지 않아도 계속 반응하게
						TweenMax.to(_menus[_index], 0.4, {alpha:1, scale:1, x : handPositionX - (handPositionX * 0.32) * -1024, y : handPositionY * 500 - 500});
						//TweenMax.to(_menus[_index], 0.4, {x : handPositionX * 400, y : handPositionY * 768});
					}	
				}
			}
		}
		
		private function throwMenu(menu : MenuPlane) : void
		{
			if (menu.isKilled) return;
			menu.isKilled = true;
			menu.isGrabbed = false;
			TweenMax.to(menu, 0.7, { bezier:[{x:_contentsContainer.x, z: -200}, {x:_contentsContainer.x, y:_contentsContainer.y, z: -10}], ease: Cubic.easeOut});
			TweenMax.to(menu, 0.35, {delay : 0.1, scale : 0.1, ease : Cubic.easeIn});
			TweenMax.to(menu, 0.2, {delay : 0.6, alpha: 0});
			var newId : uint = (_index >= 4) ? 0 : _index+1;
			setTimeout(function():void{changeContent(_index, newId)}, 800);
			
			_prevIndex = _index;
			setTimeout(function() : void{_index++;}, 2000);
		}
		
		private function grabContent() : void 
		{
			if (!_isContentGrabbed)
			{
				if (GestureModel(_model).hand1_3D.z > 1 && GestureModel(_model).hand2_3D.z > 1)
				{
					_isActive = false;
					//잡혀있던 메뉴는 원래위치로
					resetGrabbedMenu();
					//컨텐트는 중앙으로
					TweenMax.to(_contentsContainer, 0.8, {x : (GestureModel(_model).position.x - (GestureModel(_model).position.x * 0.7)) * 1024, y: 30, z: 0, ease: Cubic.easeInOut, onComplete: function():void{_isContentGrabbed = true;}});
					// 메뉴 텍스트들 사라지게
					var mx : int;
					var my : int; 
					var mz : int;
					var i : uint;
					for each (var menu: MenuPlane in _menus)
					{
		 				i = uint(menu.name.slice(-1));
						mx = _contentsContainer.x;
						mz = 0;
						my = _contentsContainer.y;
						TweenMax.to(menu, 0.7, {delay : 0.13 * i, alpha:0, scale : 0.1, x:mx, y: my, z: mz, ease: Cubic.easeInOut});
						menu.isKilled = true;
					}
				}
			}
		}
		
		private function killContent() : void
		{
			if (GestureModel(_model).hand1_3D.z < 0.9 && GestureModel(_model).hand2_3D.z < 0.9)
			{
				outro();
			}
			
			
		}
		
		private function resetGrabbedMenu() : void
		{
			var i : uint, len : uint = 4;
			for (i; i < len; ++i)
			{
				if (_menus[i].isGrabbed)
				{
					_menus[i].isGrabbed = false;
					TweenMax.to(_menus[i], 0.5, {x : _menuPositions[i].x, y : _menuPositions[i].y, z : _menuPositions[i].z, ease : Cubic.easeOut});
				}
			}
		}
		private function resetKilledMenu() : void
		{
			if (_jumpStarted) return;
			_jumpStarted = true;
			_isActive = false;
			setTimeout(function() : void{_jumpStarted = false;}, 3000);
			trace("resetKilledMenu");
			var i : uint, len : uint = 4;
			for (i; i < len; ++i)
			{
				if (_menus[i].isKilled)
				{
					reset(_menus[i]);
				}
			}
			
			function reset(menu : MenuPlane) : void
			{
				var id : uint = uint(menu.name.slice(-1));
				TweenMax.to(menu, 0.8, {alpha : 1, scale : 1, x : _menuPositions[id].x, y : _menuPositions[id].y, z : _menuPositions[id].z, ease : Cubic.easeOut, onComplete : function(){menu.isKilled = false;}});
			}
			
			changeContent(_index, 0);
			setTimeout(function() : void{
				_index=0;
				_isActive = true;
			}, 1000);
		}

		private function setContentPosition() : void
		{
			var headPosition : Vector3 = GestureModel(_model).head;
			var tx : int;
			var ty : int;
			var mx : int;
			var my : int;
			if (!headPosition) return;
			
			// head tracking
			
			tx = headPosition.x * ((1024 - 400) / 2) + 200;
			ty = headPosition.z * ((768 - 270) / 2) - 400;
			mx = headPosition.x * ((1024 - 400) / 2);
			my = headPosition.z * ((768 - 270) / 2) + 50;
			
			TweenMax.to(_contentsContainer, 0.6, {scale: 0.8, x: tx, y : ty, z : 0, ease: Cubic.easeOut});
			TweenMax.to(_menuContainer, 0.6, {scale: 0.8, x: mx, y : my, z : 0, ease: Cubic.easeOut});
		}
		
		private function setContentRotation() : void 
		{
			TweenMax.to(_contentsContainer, 2, {rotationY : GestureModel(_model).chestDirection.x * -40, ease: Cubic.easeOut});
		}
		
		private function setMenuPosition() : void 
		{
			var headPosition : Vector3 = GestureModel(_model).head;
			var hx:int = headPosition.x * ((1024 - 400) / 2);
			var mx : int;
			var mz: int;
			//var ty:int = headPosition.z * ((768 - 270) / 2) - 400;
			var f : Number;
			var i: uint, len: uint = _menus.length;
			for (i; i < len; ++i)
			{
				if (_menus[i].isGrabbed || _menus[i].isKilled) continue;
				
				mx = 200 * Math.cos(i * (Math.PI * 2 / 4) + _menuAngle) + hx;
				mz = 200 * Math.sin(i * (Math.PI * 2 / 4) + _menuAngle);
				if (_menus[i].sceneZ > -100) 
				{
					f = -_menus[i].sceneZ / 100;
					_menus[i].filters = [new BlurFilter(f, f)]; 
					_menus[i].alpha += ((1 - (_menus[i].sceneZ + 100) / 600) - _menus[i].alpha) * 0.02;
				}
				else 
				{
					_menus[i].filters = [];
					_menus[i].alpha = 1;
				}
				_menuAngle += 0.0009;
				TweenMax.to(_menus[i], 0.5, {scale : 0.8, x : mx, z : mz, ease: Cubic.easeOut});
			}
		}

		private function hitTestMenu() : void
		{
			var bodyPointX : int  = (GestureModel(_model).position.x - (GestureModel(_model).position.x * 0.7)) * 1024;
			var rect : Rectangle;
			var plane : Plane;
			var planePoint : Point;
			var i : uint, len : uint = _menus.length;
			for (i; i < len; ++i)
			{
				plane = _menus[i];
				
				//if (getIsKilled(plane)) continue;
				planePoint = new Point(plane.x, 0);
				rect = new Rectangle(planePoint.x - uint(plane.material.bitmap.width * 1 / 2), 0, uint(plane.material.bitmap.width * 1), 768);
				//if (rect.contains(bodyPointX, 0)) overMenu(i);
				
			}
		}
		
		private function getRightHandVelocityX() : Number
		{
			var currentRightHandX : Number = GestureModel(_model).rightHand.x;
			
			var velocity : Number = currentRightHandX - _prevRightHandX;
			_prevRightHandX = currentRightHandX;
			return velocity;
		}
		
		private function getHeadVelocityY() : Number
		{
			trace(GestureModel(_model).head.z)
			var velocity : Number = GestureModel(_model).head.z - _prevHeadY;
			_prevHeadY = GestureModel(_model).head.z;
			return velocity;
		}

		private function getLibraryAsset(name : String) : DisplayObject
		{
			var cls : Class = getDefinitionByName(name) as Class;
			return new cls();		
		}	
	}
}
